/* ************************************************************************* */
/*                                                                           */
/* Standard application Shell  - C Version                                   */
/* By: Keith Rollin and Jim Mensch                                           */
/*                                                                           */
/*      v1.0B1  Mensch  First Pass                                           */
/*      v1.0B2  Mensch  Included editorial corrections                       */
/*      v1.0B3  Kaar    Converted to 'C'. Calls DeskStartup() and            */
/*                      FixAppleMenu().                                      */
/*      v1.0B4  Kaar    Added comments and error checking.                   */
/*      v1.0    Kaar    First Release.                                       */
/*      v1.0.1  Mensch  Took out Desktop call.                               */
/*                                                                           */
/* ************************************************************************* */

/*********************************************************************
*                                                                    *
*             Apple IIGS Source Code Sampler, Volume I               *
*                                                                    *
*             Copyright (c) Apple Computer, Inc. 1988                *
*                       All Rights Reserved                          *
*                                                                    *
*            Written by Apple II Developer Tech Support              *
*                                                                    *
*                                                                    *
*                                                                    *
*  ----------------------------------------------------------------  *
*                                                                    *
*     This program and its derivatives are licensed only for         *
*     use on Apple computers.                                        *
*                                                                    *
*     Works based on this program must contain and                   *
*     conspicuously display this notice.                             *
*                                                                    *
*     This software is provided for your evaluation and to           *
*     assist you in developing software for the Apple IIGS           *
*     computer.                                                      *
*                                                                    *
*     DISCLAIMER OF WARRANTY                                         *
*                                                                    *
*     THE SOFTWARE IS PROVIDED "AS IS" WITHOUT                       *
*     WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,               *
*     WITH RESPECT TO ITS MERCHANTABILITY OR ITS FITNESS             *
*     FOR ANY PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO             *
*     THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH            *
*     YOU.  SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND            *
*     NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE)               *
*     ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING,             *
*     REPAIR OR CORRECTION.                                          *
*                                                                    *
*     Apple does not warrant that the functions                      *
*     contained in the Software will meet your requirements          *
*     or that the operation of the Software will be                  *
*     uninterrupted or error free or that defects in the             *
*     Software will be corrected.                                    *
*                                                                    *
*     SOME STATES DO NOT ALLOW THE EXCLUSION                         *
*     OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY              *
*     NOT APPLY TO YOU.  THIS WARRANTY GIVES YOU SPECIFIC            *
*     LEGAL RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS                *
*     WHICH VARY FROM STATE TO STATE.                                *
*                                                                    *
*                                                                    *
*********************************************************************/



#include <types.h>     
#include <prodos.h>                             
#include <misctool.h>                            
#include <quickdraw.h>                         
#include <window.h>
#include <memory.h>
#include <dialog.h>
#include <menu.h>
#include <control.h>
#include <desk.h>
#include <event.h>
#include <lineedit.h>
#include <misctool.h>
#include <locator.h>
#include <Stdfile.h>
#include <qdaux.h>
#include <print.h>
#include <font.h>
#include <intmath.h>
#include <scrap.h>
#include <texttool.h>

extern int _toolErr;


/* ************************************************************************* */
/*                                                                           */
/* Standard Global data here                                                 */
/*                                                                           */
/* ************************************************************************* */

char TitleString[]  = "\pApple IIgs Shell Application  -  C Version";
char AutString[]    = "\pBy Rollin & Mensch (c)1988 Apple Computer";
char VersString[]   = "\pVersion: 1.0                          June 17, 1988";

int MyID;
int ThisMode = mode640;                           /* init mode = 640 */
#define ScreenWidth 640

int ToolTable[] = {6,               /* number of tools to load in */
                14, 0x0100,         /* Window Manager */
                15, 0x0100,         /* Menu Manager */
                16, 0x0100,         /* Control Mnager */
                20, 0x0100,         /* Line Edit */
                21, 0x0100,         /* Dialog Manager */
                22, 0x0100          /* Scrap Manager  */
                
            /*  18, 0x0100,         /* QD Aux */
            /*  19, 0x0100,         /* Print Manager */
            /*  23, 0x0100,         /* Standard File */
            /*  25, 0x0100,         /* Note Synthesizer */
            /*  27, 0x0100,         /* Font Manager */
            /*  28, 0x0100,         /* List manager */
            /*  29, 0x0100,         /* ACE Tools */
            /*  32, 0x0100,         /* MIDI Tools */
                };

/* The following is used when it is time to quit this application. When the */
/* user selects "Quit" from the File menu, the program sets the QuitFlag    */
/* to a non-zero value. This is the condition that tells the main event     */
/* loop to stop and return to the calling procedure.                        */

boolean QuitFlag;

/* The following is the record that is used by TaskMaster to return events. */
/* It is similar to a regular event record, except that there are two       */
/* additional fields at the end. The first is used to convey some TaskMaster*/
/* specific data back to the application. The second is called the TaskMask */
/* and is used to tell TaskMaster what situations to handle. In this shell, */
/* we tell TaskMaster to handle everything by setting all currently defined */
/* bits to 1.                                                               */
        
WmTaskRec EventRec = {              /* Data block to hold event records */
        0,
        0L,
        0L,
        0,0,
        0,
        0L,
        0x0000FFFFL};               /* Let TaskMaster do it all! */


/* We take the easy way out and use the Dialog Manager call NoteAlert() to  */
/* display our About box. We provide the strings and buttons, and it puts   */
/* it all in a window, adds an icon, and handles a events until the OK      */
/* button is pressed.                                                       */

ItemTemplate OKButton = {
        ok,                         /* item number (predefined in Dialog.h) */
        50,500,65,550,              /* bounding rectangle */
        buttonItem,                 /* simple button type */
        "\pOK",                     /* Pointer to its name */
        0,                          /* initial value */
        0,                          /* item flag (invisibility, etc.) */
        NULL};                      /* pointer to color table (NULL=Default) */

ItemTemplate AboutTitle = {
        2,
        10,100,20,550,
        statText+itemDisable,
        TitleString,
        0,
        0,
        NULL};

ItemTemplate AboutAut = {
        3,
        25,100,35,550,
        statText+itemDisable,
        AutString,
        0,
        0,
        NULL};

ItemTemplate AboutVers = {
        4,
        40,100,50,550,
        statText+itemDisable,
        VersString,
        0,
        0,
        NULL};

AlertTemplate AboutBox = {
        30,30,100,590,              /* for 320 mode, use 30,30,100,290 */
        1,                          /* This is Alert #1 */
        0x80,0x80,0x80,0x80,        /* Alert stages - all silent */
        &OKButton,                  /* Ptr to OK button item */
        &AboutTitle,                /* Ptr to name of the program */
        &AboutAut,                  /* Ptr to name of the author */
        &AboutVers,                 /* Ptr to version number/date */
        NULL};                      /* Long $0 to end the list */


/* ************************************************************************* */
/*                                                                           */
/* Application specific data appears here                                    */
/*                                                                           */
/* ************************************************************************* */


/* ************************************************************************* */
/*                                                                           */
/* This is an array or characters used to define the menus. Each line starts */
/* off with an identifying character as defined by the Menu Manager Chapter. */
/* It then contains either a Menu Title or Menu Item string, followed by a   */
/* backslash (\\) and any modifiers and ID numbers. Each line is then term-  */
/* inated with a carriage return (\r).                                       */
/*                                                                           */
/* Our sample programs use menus that start at 250. The Edit menu items are  */
/* entered first to conform to the menu manager documentation. The About     */
/* and Quit menu items use IDs 256 and 257 as a convention.                  */
/*                                                                           */
/* ************************************************************************* */

#define Num_Menus 3

char *Menus[] = {
"$$  Edit  \\DN3\r\
--Undo\\V*ZzN250\r\
--Cut\\*XxN251\r\
--Copy\\*CcN252\r\
--Paste\\V*VvN253\r\
--Clear\\N254\r",

"$$  File  \\N2\r\
--Close\\DVN255\r\
--Quit\\*QqN257\r",

"$$@\\XN1\r\
--About C Shell...\\VN256\r"};


char **y,*z;            /* ZPHandle and ZPPointer */


/* ************************************************************************* */
/*                                                                           */
/* This is the core of the program. It simply calls all the other routines   */
/* in order.                                                                 */
/*                                                                           */
/* ************************************************************************* */
main()
{
    InitTools();            /* initialize tools */
    InitApp();              /* initialize application specific stuff */
    ShowCursor();
    EventLoop();            /* do your stuff */
    ShutDownApp();          /* until user wants to  */
    ShutDownTools();        /*   do something else!   */
}


/* ************************************************************************* */
/*                                                                           */
/* ErrorCheck - Called to InitTools to check for startup errors.             */
/*                                                                           */
/* ************************************************************************* */

char DeathMsg[] = "Fatal error $0000 has occurred at 0000. Press any key to exit:";

void ErrorCheck(where)
    int where;
{
      if (_toolErr)
     {
       Int2Hex(_toolErr,DeathMsg + 13 ,4);  /* Stick error # into a string */
       Int2Hex(where,DeathMsg + 34 ,4); /* Stick location # into a string */
       GrafOff();                           /* Turn off Super Hires */
       WriteCString(DeathMsg);              /* Print the error message */
       SysBeep();                           /* Danger, Will Robinson!!! */
       ReadChar(0);                         /* Pause for a character */
       ShutDownTools();                     /* ShutDown my Tools */
       exit(1);                             /* Run like a coward */
     }
}


/* ************************************************************************* */
/*                                                                           */
/* InitTools - This routine start up all the tools that will be needed by    */
/* your application.                                                         */
/*                                                                           */
/* ************************************************************************* */

#define QDDPage     0
#define EMDPage     0x0300  /* QDDPage+0x0300 */
#define CtlDPage    0x0400  /* EMDPage+0x0100 */
#define MenuDPage   0x0500  /* CtlDPage+0x0100 */
#define LEDPage     0x0600  /* MenuDPage+0x0100 */
#define ToolDPSize  0x0700L /* LEDPage+0x0100 - 'L' forces to 32 bit value */

InitTools()
{
    TLStartUp();                                /* for calling tools */
    ErrorCheck(1);                              /* Make sure all is OK      */
    MyID = MMStartUp();                         /* ID for all transactions */
    ErrorCheck(2);                              /* Make sure all is OK      */
    MTStartUp();                                /* Misc. Tools  */
    ErrorCheck(3);                              /* Make sure all is OK      */
    
    y = NewHandle(ToolDPSize,
                MyID,                           /* put it to my name    */
                attrLocked+attrFixed+attrPage+attrBank,
                0L);
    ErrorCheck(4);                              /* Make sure all is OK      */
    z = *y;                                     /* deref handle     */
    
    LoadTools(ToolTable);
    ErrorCheck(5);                              /* Make sure all is OK      */
    
    QDStartUp((int) z + QDDPage,ThisMode,0,MyID);
    ErrorCheck(6);                              /* Make sure all is OK      */
    
    EMStartUp((int) z + EMDPage,20,0,ScreenWidth,0,200,MyID);
    ErrorCheck(7);                              /* Make sure all is OK      */
    
    WindStartUp(MyID);
    ErrorCheck(8);                              /* Make sure all is OK      */
    
    CtlStartUp(MyID,(int) z + CtlDPage);
    ErrorCheck(9);                              /* Make sure all is OK      */
    
    MenuStartUp(MyID,(int) z + MenuDPage);
    ErrorCheck(10);                             /* Make sure all is OK      */
    
    LEStartUp(MyID,(int) z + LEDPage);
    ErrorCheck(11);                             /* Make sure all is OK      */
    
    DialogStartUp(MyID);
    ErrorCheck(12);                             /* Make sure all is OK      */
    
    ScrapStartUp();                             /* no errors possible from these 2 */
    DeskStartUp();                              /* All we need is init'ed now */
    
    /* Insert application specific tools here */
    
    RefreshDesktop(0L);
    
}

/* ************************************************************************* */
/*                                                                           */
/* ShutDownTools - Shuts down all of the tools started by InitTools().       */
/*                                                                           */
/* ************************************************************************* */

ShutDownTools()
{
    DeskShutDown();
    ScrapShutDown();
    DialogShutDown();
    LEShutDown();
    MenuShutDown();
    CtlShutDown();
    WindShutDown();
    EMShutDown();
    QDShutDown();
    MTShutDown();
    
    DisposeHandle(y);
    
    MMShutDown(MyID);
    TLShutDown();
}


/* ************************************************************************* */
/*                                                                           */
/* InitApp - This routine is called once after the tools are started. This   */
/* is where you would create your menus, and other objects your program will */
/* need at the very start.                                                   */
/*                                                                           */
/* ************************************************************************* */
InitApp()
{
    int i;

    QuitFlag = false;
    
    /* Loop through the array of menu text, and use it to create our menus */
    for (i=0;i < Num_Menus;i++)
        InsertMenu(NewMenu(Menus[i]),0);
    
    FixAppleMenu(1);                /* install NDAs available */
    FixMenuBar();                   /* Call CalcMenuSize() for all menus */
    DrawMenuBar();                  /* Draw the thing on the screen */
}



/* ************************************************************************* */
/*                                                                           */
/* ShutDownApp - This routine is called once at the end of your program, but */
/* before the tools are shut down. Take this opportunity to clean up after   */
/* yourself if you need to.                                                  */
/*                                                                           */
/* ************************************************************************* */
ShutDownApp()
{
    /* Currently does nothing */
}


/* ************************************************************************* */
/*                                                                           */
/* InContent - This routine gets called when the user clicks in the content  */
/* region of a window. What happens here is up to you.                       */
/*                                                                           */
/* ************************************************************************* */
InContent()
{
    /* Currently does nothing */
}


/* ************************************************************************* */
/*                                                                           */
/* Ignore - called when an event occurs that you don't want/need to handle   */
/*                                                                           */
/* ************************************************************************* */
Ignore()
{
    /* Does nothing */
}


/* ************************************************************************* */
/*                                                                           */
/* DoAbout - Show the vanity box until the OK button is hit. Calls           */
/* NoteAlert to display a dialog box with an icon and handle mouse clicks.   */
/*                                                                           */
/* ************************************************************************* */
DoAbout()
{
    NoteAlert(&AboutBox,NULL);
}

/* ************************************************************************* */
/*                                                                           */
/* DoUpdate - This routine is called if you have a window and the Event      */
/* Manager notices that it needs to have some or all of it redrawn.          */
/*                                                                           */
/* ************************************************************************* */
DoUpdate()
{
    /* Put your update routine here */
}


/* ************************************************************************* */
/*                                                                           */
/* DoQuit - Set the quit flag. This tells the Event loop to exit.            */
/*                                                                           */
/* ************************************************************************* */
DoQuit()
{
    QuitFlag = true;
}


/* ************************************************************************* */
/*                                                                           */
/* MenuSelect - Called when TaskMaster returns a menu event. This routine    */
/* takes the menu item that was hit and calculates an offset into the menu   */
/* dispatch table. It then calls that routine.                               */
/*                                                                           */
/* ************************************************************************* */
WordProcPtr Routines[] = {
    (WordProcPtr) Ignore,       /* Undo */
    (WordProcPtr) Ignore,       /* Cut */
    (WordProcPtr) Ignore,       /* Copy */
    (WordProcPtr) Ignore,       /* Paste */
    (WordProcPtr) Ignore,       /* Clear */
    (WordProcPtr) Ignore,       /* Close */
    (WordProcPtr) DoAbout,      /* Bring up the vanity box */
    (WordProcPtr) DoQuit        /* Set the quit flag */
    };
    
DoMenuSelect()
{
    /* The menu ID of the item selected is in 'wmTaskData'. Since these IDs */
    /* start at 250, subtract 250 from the ID to turn it into an index. This*/
    /* index is used to call a routine in a table of routines. */
    
    (*Routines[EventRec.wmTaskData-250])();
    
    /* The routine has been called. Unhilite the menu and return to the Main*/
    /* Event Loop. */
    
    HiliteMenu(0,*(word *)((Pointer)(((long)&EventRec.wmTaskData)+2)));
}


/* ************************************************************************* */
/*                                                                           */
/* EventLoop - This routine is the heart of your application. It is repeat-  */
/* edly called and when the user selects/operates something, it dispatches   */
/* to a routine to do the proper thing.                                      */
/*                                                                           */
/* ************************************************************************* */
EventLoop()
{
    word theTask;
    
    do {
    theTask = TaskMaster(everyEvent,&EventRec); /* Get event from TaskMaster */
    switch (theTask) {                  /* switch on the event type. */
        case updateEvt:                 /* Handle updates. */
            DoUpdate();
            break;                      /* break out of 'switch' statement */
        case wInMenuBar:                /* Handle selections in Special */
        case wInSpecial:                /* and normal menu item selects */
            DoMenuSelect();
            break;                      /* break out of 'switch' statement */
        case wInContent:                /* Handle a click in the content */
            InContent();                /* region. */
            break;                      /* break out of 'switch' statement */
        }
    } while (!QuitFlag);                    /* Loop until "Quit" is selected */
}
